package cn.geodata.dataview.action;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import org.apache.log4j.Logger;
import org.geotools.data.DataStore;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.factory.GeoTools;
import org.geotools.feature.Feature;
import org.geotools.feature.FeatureCollection;
import org.geotools.feature.FeatureIterator;
import org.geotools.feature.FeatureType;
import org.opengis.filter.Filter;
import org.opengis.filter.FilterFactory2;

import cn.geodata.dataview.Fire;
import cn.geodata.dataview.FireFactory;
import cn.geodata.dataview.util.Util;

import com.vividsolutions.jts.geom.Polygon;

public class Search {
	private static Logger Log = Logger.getLogger(Search.class);
	
	private double minx;
	private double miny;
	private double maxx;
	private double maxy;
	
	private Date start;
	private Date end;
	
	private Fire[] fires;
	
	private FeatureCollection featureCollection;

	public double getMinx() {
		return minx;
	}

	public void setMinx(double minx) {
		this.minx = minx;
	}

	public double getMiny() {
		return miny;
	}

	public void setMiny(double miny) {
		this.miny = miny;
	}

	public double getMaxx() {
		return maxx;
	}

	public void setMaxx(double maxx) {
		this.maxx = maxx;
	}

	public double getMaxy() {
		return maxy;
	}

	public void setMaxy(double maxy) {
		this.maxy = maxy;
	}

	public Date getStart() {
		return start;
	}

	public void setStart(Date start) {
		this.start = start;
	}

	public Date getEnd() {
		return end;
	}

	public void setEnd(Date end) {
		this.end = end;
	}

	public String execute() throws Exception {
		Log.info("minx:" + this.minx);
		Log.info("maxx:" + this.maxx);
		Log.info("miny:" + this.miny);
		Log.info("maxy:" + this.maxy);
		Log.info("Start:" + this.start);
		Log.info("end:" + this.end);
		
		this.featureCollection = this.queryPathAndRow();
		this.fires = this.queryFires();
		
		Log.info("Fire count:" + fires.length);		
		return "success";
	}
	
	protected FeatureCollection queryPathAndRow() throws Exception {
		DataStore _dataStore = Util.loadTmDataStore();
		FeatureType _featureType = _dataStore.getSchema(_dataStore.getTypeNames()[0]);
		
		Polygon _polygon = Util.createBox(this.minx, this.miny, this.maxx, this.maxy);
		
		FilterFactory2 _filterFactory = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints());
		Filter _filter = _filterFactory.intersects(_filterFactory.property(_featureType.getDefaultGeometry().getLocalName()), _filterFactory.literal(_polygon));
		
		return _dataStore.getFeatureSource(_featureType.getTypeName()).getFeatures(_filter);
	}
	
	public ArrayList<int[]> getPathAndRows() throws Exception {
		ArrayList<int[]> _list = new ArrayList<int[]>();
		
		FeatureIterator _it = this.featureCollection.features();
		while(_it.hasNext()){
			Feature _f = _it.next();
			int _path = ((Integer)_f.getAttribute("PATH")).intValue();
			int _row = ((Integer)_f.getAttribute("ROW")).intValue();
			
			_list.add(new int[]{_path, _row});
		}
		_it.close();
		
		return _list;
	}

	public FeatureCollection getFeatureCollection() {
		return featureCollection;
	}
		
	protected Fire[] queryFires() throws Exception{
		String _sql = "";
		DateFormat _format = new SimpleDateFormat("yyyy-MM-dd");
		if(this.start != null){
			if(_sql.length() > 0){
				_sql += " AND ";
			}
			_sql += "date >= '" + _format.format(this.start) + "'";
		}
		if(this.end != null){
			if(_sql.length() > 0){
				_sql += " AND ";
			}
			_sql += "date >= '" + _format.format(this.end) + "'";
		}
		
		String _sql2 = "";
		ArrayList<int[]> _list = this.getPathAndRows();
		for (int[] _is : _list) {
			if(_sql2.length() > 0){
				_sql2 += " OR ";
			}
			_sql2 += "(path=" + _is[0] + " AND row=" + _is[1] + ")";
		}
		
		if(_sql2.length() > 0){
			if(_sql.length() > 0){
				_sql += " AND ";
			}
			_sql += "(" + _sql2 + ")";
		}
		
		Log.info("SQL:" + _sql);

		FireFactory _factory = new FireFactory();
		return _factory.list(_sql).toArray(new Fire[0]);
	}

	public Fire[] getFires() {
		return fires;
	}
}
